package com.snail.cloud.config;

import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTCreator;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.snail.cloud.model.UserDetailsImpl;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;


public class JwtTokenUtil {

    private final static Logger logger = LoggerFactory.getLogger(JwtTokenUtil.class);
    /**
     * Token 盐值\密钥, 请注意修改
     */
    public final static String SECRET_KEY = "secret-snail-0302";

    public final static Long EXPIRE_TIME = 3600000L;

    public static String generateToken(UserDetailsImpl userDetail) {
        Map<String, String> claims = new HashMap<>();
        claims.put("salt", userDetail.getIotUser().getSalt().toString());
        claims.put("username", userDetail.getUsername());
        claims.put("userId", userDetail.getIotUser().getUserId().toString());
        return createToken(claims);
    }

    public static String getUserId(String token) {
        try {
            JWTVerifier verifier = JWT.require(Algorithm.HMAC256(SECRET_KEY)).build();
            DecodedJWT jwt = verifier.verify(token);
            return jwt.getClaim("userId").asString();
        } catch (Exception e) {
            logger.error("token验证失败", e);
            return null;
        }
    }

    public static String getJwtId(String token) {
        try {
            JWTVerifier verifier = JWT.require(Algorithm.HMAC256(SECRET_KEY)).build();
            DecodedJWT jwt = verifier.verify(token);
            return jwt.getClaim("jti").asString();
        } catch (Exception e) {
            logger.error("token验证失败", e);
            return null;
        }
    }


    private static String createToken(Map<String, String> claims) {
        Date now = new Date();
        Date expiration = new Date(now.getTime() + 1 * 60 * 60 * 1000);
        JWTCreator.Builder builder = JWT.create();
        claims.forEach(builder::withClaim);
        return builder
                .withJWTId(UUID.randomUUID().toString())
                .withExpiresAt(expiration)
                .sign(Algorithm.HMAC256(SECRET_KEY));
    }

    public static Boolean validateToken(String token) {
        JWTVerifier jwtVerifier = JWT.require(Algorithm.HMAC256(SECRET_KEY)).build();

        DecodedJWT decode;
        try {
            /*开始进行验证，该函数会验证此token是否遭到修改，
                以及是否过期，验证成功会生成一个解码对象
                ，如果token遭到修改或已过期就会
                抛出异常，我们用try-catch抓一下*/
            decode = jwtVerifier.verify(token);
        } catch (Exception e) {
            //抛出异常，验证失败
            return false;
        }

        Long id = decode.getClaim("id").asLong();
        String username = decode.getClaim("username").asString();
        logger.info("id:{},username:{}", id, username);
        return true;
    }
}
